package com.xyq.fs.base;

import java.io.IOException;
import java.nio.file.Paths;

import java.util.HashSet;
import java.util.Set;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.CharArraySet;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.IndexSearcher;

import org.apache.lucene.index.IndexWriterConfig.OpenMode;
import org.apache.lucene.index.LogByteSizeMergePolicy;
import org.apache.lucene.index.LogMergePolicy;
import org.apache.lucene.store.FSDirectory;
import com.xyq.fs.constants.FieldConstant;
import com.xyq.fs.scan.ScanFileInf;
import com.xyq.fs.views.MyAlert;
import com.xyq.fs.views.WindowsGo;

import javafx.application.Platform;

public class MyDirectoryS {

	private static String dirName = "lucenedirs2";
	private static FSDirectory dir;
	public static IndexWriter writer;
	private static IndexWriterConfig writerConfig;
	/**
	 * 这个read主要是为了全盘索引用的
	 */
	public static IndexReader reader;
	/**
	 * 这个是自定义过滤表，没有过滤任何词汇，保证完全可搜索
	 */
	private static Set<String> stopWords = new HashSet<>();
	// static {
	// stopWords.add(" ");
	// }
	private static CharArraySet cs = new CharArraySet(stopWords, true);
	private static Analyzer analyzer = new StandardAnalyzer(cs);

	public static IndexSearcher searcher;

	public static void init() {

	}

	/**
	 * 初始化
	 */
	static {
		new Thread(() -> {
			try {
				dir = FSDirectory.open(Paths.get(System.getProperty("user.dir") + "\\CONF\\" + dirName));
				writerConfig = new IndexWriterConfig(analyzer);
				LogMergePolicy mergePolicy = new LogByteSizeMergePolicy();
				writerConfig.setRAMBufferSizeMB(1);
				mergePolicy.setMergeFactor(2);
				writerConfig.setMergePolicy(mergePolicy);
				writerConfig.setRAMPerThreadHardLimitMB(1);
				writerConfig.setOpenMode(OpenMode.CREATE_OR_APPEND);
				// writerConfig.setUseCompoundFile(false);
				try {
					writer = new IndexWriter(dir, writerConfig);
				} catch (Exception e) {
					WindowsGo.close2();
					if (e instanceof org.apache.lucene.store.LockObtainFailedException)
						MyAlert.alertError("您当前正在运行着一个工具,请勿重复启动!!!(3秒后自动关闭)");
					else
						MyAlert.alertError("启动失败!!!");
					try {
						Thread.sleep(3000);
						System.exit(0);
					} catch (Exception e1) {

					}

				}

				// 第一次索引后如果索引文件巨大会卡顿，用线程

				try {
					writer.commit();
					WindowsGo.sf = new ScanFileInf();
					reader = DirectoryReader.open(writer);
					searcher = new IndexSearcher(reader);
					WindowsGo.GO = 0;
					Platform.runLater(() -> {
						WindowsGo.tsB.setText("");
					});
					if (WindowsGo.rbtnC.isSelected()) {
						WindowsGo.autoScan();
					}
					WindowsGo.preLoad();

				} catch (IOException e) {
					e.printStackTrace();
				}

			} catch (IOException e) {
				e.printStackTrace();
			}
		}).start();

	}

	public static IndexSearcher getIndexSearcher() {

		if (searcher == null)
			return new IndexSearcher(reader);
		return searcher;
	}

	public static IndexReader getRtIndexReader() {

		try {
			reader = DirectoryReader.open(writer);
			return reader;
		} catch (IOException e) {
			e.printStackTrace();
		}
		return reader;
	}

	public synchronized static void updateReaderAndSearcher() {

		new Thread(() -> {
			if (writer.isOpen()) {
				getRtIndexReader();
				searcher = new IndexSearcher(reader);
			}
		}).start();

	}

	/***
	 * 这个操作其实就是更新操作
	 * 
	 * @param doc
	 */
	public static void addDocument(Document doc) {

		try {
			if (writer.isOpen()) {
				Term term = new Term(FieldConstant.FILE_PATH, doc.get(FieldConstant.FILE_PATH));
				writer.updateDocument(term, doc);
				term = null;
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public static void commit() {

		new Thread(() -> {
			try {
				if (writer != null && writer.isOpen())
					writer.commit();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}).start();
	}

	public static void closeAll() {

		if (reader != null)
			try {
				reader.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		if (writer != null && writer.isOpen())
			try {
				writer.flush();
				writer.commit();
				writer.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
	}

	public static void updates() {

		MyDirectoryS.updateReaderAndSearcher();
		MyDirectoryS.commit();
		System.gc();
	}
}
